<?php
namespace Monkey\Database\Driver;

use MonkeyException;

/**
 * Mysql数据库驱动\Monkey\Database\Driver\Mysql
 * @package    Monkey\Database\Driver
 * @author     HuangYi
 * @copyright  Copyright (c) 2011-07-01——2013-03-30
 * @license    New BSD License
 * @version    $Id: \Monkey\Database\Driver\Mysql.php 版本号 2013-03-30 $
 */
class Mysql implements _Interface
{
    private $_linker;    //连接
    private $_sql;       //
    private $_prefix;
    private $_result;    //
    private $_fetch_model=array(
        'assoc'=>MYSQL_ASSOC,
        'num'=>MYSQL_NUM,
        'both'=>MYSQL_BOTH
    );
    private $_execute_true;
    public function __construct($config,$isTest=false) {
        if(!extension_loaded('mysql')){
            MonkeyException::halt('没有安装mysql驱动扩展,请先在php.ini中配置安装mysql',1024,__FILE__,__LINE__);
        }
        if(!$isTest){
            $this->_linker= $this->connect($config,false);
        }
    }
    public function connect($config,$isTest=false){
        $linker=mysql_connect($config['host'].':'.$config['port'],$config['username'],$config['password']);
        if($linker===false || !mysql_select_db($config['dbname'],$linker)){
            if($isTest)return notice(false,array('msg'=>mysql_error(),'code'=>mysql_errno()));
            else MonkeyException::halt('连接数据库时出错：'.mysql_error(),mysql_errno(),__FILE__,__LINE__);
        }
        if($isTest)return notice(true,array('msg'=>'连接成功','code'=>NULL));
        $this->_prefix=$config['prefix']?$config['prefix']:'';
        if(!is_null($this->_linker))mysql_close($this->clear()->_linker);
        mysql_set_charset($config['charset'],$linker);
        $this->_linker=$linker;
        return true;
    }
    public function escape($data) {
        if (is_array($data)) return array_map(array($this,'escape'), $data);
        if (is_null($data)) return 'NULL';
        if (is_bool($data)) return $data ? '1' : '0';
        if (is_int($data)) return (int) $data;
        if (is_float($data)) return (float) $data;
        $data = sql_encode($data);
        return '"' . mysql_real_escape_string($data, $this->_linker). '"' ; // 注意mysqli_real_escape_string的参数位置
    }
    public function getPreFix(){
        return $this->_prefix;
    }
    public function transaction($type) {
        if($type===0 or $type=='begin'){
            mysql_query('BEGIN', $this->_linker);
        }elseif($type===1 or $type=='commit'){
            mysql_query('COMMIT', $this->_linker);
        }elseif($type===-1 or $type=='rollback'){
            mysql_query('ROLLBACK', $this->_linker);
        }
        return $this;
    }
    public function query($sql,$params=null) {
        $this->clear();
        $this->_sql = preg_replace('/\{:(\S+?):\}/',$this->_prefix.'$1',$sql);
        $this->_result=mysql_query($sql, $this->_linker);
        $this->_execute_true = (bool)$this->_result;
        return $this;
    }
    public function isSuccess(){
        return $this->_execute_true;
    }
    public function resultCount() {
        if(!is_resource($this->_result))return null;
        return mysql_num_rows($this->_result);
    }
    public function resultAll($model=FETCH_ASSOC){
        if(!is_resource($this->_result))return null;
        $model=$this->_fetch_model[$model];
        $result=array();
        while ($row = mysql_fetch_array($this->_result, $model)) {
            $result[]=$row;
        }
        mysql_free_result($this->_result);
        return sql_decode($result);
    }
    public function result($model=FETCH_ASSOC){
        if(!is_resource($this->_result))return null;
        return sql_decode(mysql_fetch_array($this->_result, $this->_fetch_model[$model]));
    }
    public function affectedRows() {
        return $this->_execute_true ? mysql_affected_rows($this->_linker) : NULL;
    }
    public function insertId() {
        return $this->_execute_true ? mysql_insert_id($this->_linker) : NULL;
    }
    public function lastSql(){
        return $this->_sql;
    }
    public function errorCode() {
        return mysql_errno($this->_linker);
    }
    public function errorMessage() {
        return mysql_error($this->_linker);
    }
    public function clear() {
        $this->_sql = '';
        if(is_resource($this->_result))mysql_free_result($this->_result);
        return $this;
    }
    public function destroy() {
        $this->clear();
        if(is_resource($this->_linker))mysql_close($this->_linker);
    }
}